#include <windows.h>
#include <stdio.h>
#include "window.h"
#include "tryicon.h"
#include "subprocess.h"
#include "utils.h"

struct tryicon g_tryicon;
struct window g_window;
HANDLE g_thread;
HANDLE g_stop_event;
HANDLE g_cmd_event;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

DWORD WINAPI checker_thread(LPVOID lpParameter)
{
    struct subprocess mreader;
    char last_status[128];
    wchar_t ustr[200];
    wchar_t cmd_line[MAX_PATH];
    HANDLE handles[2];

    handles[0] = g_stop_event;
    handles[1] = g_cmd_event;

    if (subprocess_init(&mreader) == -1)
    {
        error_exit("Cannot init mreader");
    }
    wcscpy_s(cmd_line, MAX_PATH, L"check.bat");
    if (subprocess_start(&mreader, cmd_line) == -1)
    {
        error_exit("Cannot start mreader");
    }

    while (1)
    {
        if (subprocess_write(&mreader, "read\n") == -1)
        {
            error_exit("Cannot send command to mreader");
        }

        if (subprocess_read(&mreader, last_status, 200))
        {
            a2w(last_status, ustr, 200);
            tryicon_display(&g_tryicon, ustr);
            window_append_text(&g_window, ustr);
        }

        if (WAIT_OBJECT_0 == WaitForMultipleObjects(2, handles, FALSE, 300000))
        {
            break;
        }
    }

    if (subprocess_write(&mreader, "quit\n") == -1)
    {
        error_exit("Cannot send quit command to mreader");
    }

    if (subprocess_wait(&mreader) == -1)
    {
        error_exit("Cannot wait mreader");
    }

    if (subprocess_close(&mreader) == -1)
    {
        error_exit("Cannot close mreader");
    }

    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR args, int cmd_show)
{
    MSG msg ;
    WNDCLASSEXW wnd = {0};

    wnd.hInstance = hInstance;
    wnd.lpszClassName = L"tryicon";
    wnd.lpfnWndProc = WndProc;
    wnd.style = CS_HREDRAW | CS_VREDRAW ;
    wnd.cbSize = sizeof(WNDCLASSEXW);

    wnd.hIcon = LoadIcon(NULL, IDI_WINLOGO);
    wnd.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
    wnd.hCursor = LoadCursor(NULL, IDC_ARROW);
    wnd.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE ;

    window_init(&g_window);
    if (window_create(&g_window, &wnd, cmd_show) == -1)
    {
        error_exit("window_create");
    }
    tryicon_init(&g_tryicon, g_window.hwnd);

    g_stop_event = CreateEvent(NULL, FALSE, FALSE, NULL);
    g_cmd_event = CreateEvent(NULL, FALSE, FALSE, NULL);
    g_thread = CreateThread(NULL, 0, checker_thread, NULL, 0, NULL);
    if (g_thread == NULL)
    {
        error_exit("Cannot start checking thread");
    }

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    tryicon_delete(&g_tryicon);
    window_minimize(&g_window);
    CloseHandle(g_stop_event);
    CloseHandle(g_cmd_event);

    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    CREATESTRUCT* cs;
    struct window* w = (struct window*)GetWindowLongPtr(hwnd, GWLP_USERDATA);

    switch (message)
    {
    case WM_COMMAND:
        if (LOWORD(wParam) == ID_CHECK_NOW)
        {
            SetEvent(g_cmd_event);
            return 0 ;
        }
        break;

    case WM_CREATE:
        cs = (CREATESTRUCT*)lParam;
        w = (struct window*)cs->lpCreateParams;
        window_on_create(w);
        return 0 ;
        break;

    case WM_SIZE:
        window_size(w, (int)wParam, LOWORD(lParam), HIWORD(lParam));
        return 0 ;
        break;

    case WM_SYSCOMMAND:
        switch (wParam & 0xfff0)
        {
        case SC_MINIMIZE:
        case SC_CLOSE:
            window_minimize(w);
            return 0 ;
            break;
        }
        break;

    case WM_TRAYICON:
    {
        switch (wParam)
        {
        case ID_TRAY_APP_ICON:
            break;
        }

        if (lParam == WM_LBUTTONUP)
        {
            window_restore(w);
        }
        else if (LOWORD(lParam) == WM_CONTEXTMENU)
        {
            window_track_menu(w);
        }
    }
    break;

    case WM_CLOSE:
        window_minimize(w);
        return 0;
        break;

    case WM_DESTROY:
        SetEvent(g_stop_event);
        WaitForSingleObject(g_thread, INFINITE);
        PostQuitMessage(0);
        break;

    }

    return DefWindowProc(hwnd, message, wParam, lParam) ;
}

